package demo.axitdn;

import demo.axitdn.physic.Accumulator;
import android.graphics.Canvas;

public class GameLoopThread extends Thread {
	static final long MPT = 33;
	static final long FPS = 33;
	private GameView view;
	private boolean running = false;

	// desired fps
	private final static int MAX_FPS = 30;
	// maximum number of frames to be skipped
	private final static int MAX_FRAME_SKIPS = 5;
	// the frame period
	private final static int FRAME_PERIOD = 1000 / MAX_FPS;

	public GameLoopThread(GameView view) {
		this.view = view;
	}

	public void setRunning(boolean run) {
		running = run;
	}

	@Override
	public void run() {
		double currentTime = hires_time_in_seconds();
		Accumulator acu = new Accumulator();
		acu.accumulator = 0;

		long beginTime; // the time when the cycle begun
		long timeDiff; // the time it took for the cycle to execute
		int sleepTime; // ms to sleep (<0 if we're behind)
		int framesSkipped; // number of frames being skipped

		sleepTime = 0;
		while (running) {
			Canvas c = null;
			double newTime = hires_time_in_seconds();
			double frameTime = newTime - currentTime;
			if (frameTime > 0.25) {
				frameTime = 0.25f; // note: max frame time to avoid spiral of
									// death
			}
			currentTime = newTime;

			acu.accumulator += frameTime;
			try {
				c = view.getHolder().lockCanvas();
				synchronized (view.getHolder()) {
					beginTime = System.currentTimeMillis();
					framesSkipped = 0; // resetting the frames skipped
					view.onUpdate(acu);
					view.onDraw(c);
					timeDiff = System.currentTimeMillis() - beginTime;
					// calculate sleep time
					sleepTime = (int) (FRAME_PERIOD - timeDiff);

					if (sleepTime > 0) {
						// if sleepTime > 0 we're OK
						try {
							// send the thread to sleep for a short period
							// very useful for battery saving
							Thread.sleep(sleepTime);
						} catch (InterruptedException e) {
						}
					}

					while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
						// we need to catch up
						// update without rendering
						view.onUpdate(acu);
						// add frame period to check if in next frame
						sleepTime += FRAME_PERIOD;
						framesSkipped++;
					}
				}
			} finally {
				if (c != null) {
					view.getHolder().unlockCanvasAndPost(c);
				}
			}
		}
	}

	private double hires_time_in_seconds() {
		// TODO Auto-generated method stub
		return System.currentTimeMillis() / 1000.0;
	}
}
